bitkeeper revision 1.310 (3f0bf553kbldKc8vu6lujXO6BTBWpg)
authorsos22@labyrinth.cl.cam.ac.uk <sos22@labyrinth.cl.cam.ac.uk>
Wed, 9 Jul 2003 10:58:27 +0000 (10:58 +0000)
committersos22@labyrinth.cl.cam.ac.uk <sos22@labyrinth.cl.cam.ac.uk>
Wed, 9 Jul 2003 10:58:27 +0000 (10:58 +0000)
Misc. tidy ups.  Continue moving bits of teh /proc interface
from stupidly overloaded calls to read and write to using
a slightly less awful ioctl interface.

tools/internal/mem_defs.h
tools/internal/xi_build.c
xen/include/hypervisor-ifs/dom0_ops.h
xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c
xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_memory.c

index a9a1441d6154ef85a43e17729ba9ee4bcc2c9810..4ba84ffaeefee36f0057743a2d77cec026ded85c 100644 (file)
@@ -42,4 +42,4 @@ typedef struct { unsigned long l2_lo; } l2_pgentry_t;
 
 /* local definitions */
 
-#define nr_2_page(x) (x << PAGE_SHIFT)
+#define nr_2_page(x) ((x) << PAGE_SHIFT)
index 1457281f74459b922e55bf4b81eae014af0295ec..c8dfc7878646724babb553fdcd64c2a346c49a88 100644 (file)
@@ -8,13 +8,11 @@
 #include <stdio.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <stdlib.h>
 #include <sys/ioctl.h>
+#include <string.h>
+#include <stdlib.h>
 
-#include "asm-i386/types.h"
 #include "hypervisor-ifs/hypervisor-if.h"
 #include "dom0_ops.h"
 #include "dom0_defs.h"
@@ -51,7 +49,7 @@ static void dom_mem_cleanup(dom_mem_t * dom_mem)
 {
     int fd;
     struct dom0_unmapdommem_args argbuf;
-
+           
     fd = open("/proc/xeno/dom0_cmd", O_WRONLY);
     if(fd < 0){
         perror(PERR_STRING);
@@ -68,85 +66,33 @@ static void dom_mem_cleanup(dom_mem_t * dom_mem)
     close(fd);
 }
 
-/* ask dom0 to export domains memory through /proc */
-static int setup_dom_memmap(unsigned long pfn, int pages, int dom)
-{
-    char cmd_path[MAX_PATH];
-    dom0_op_t dop;
-    int cmd_fd;
-
-    dop.cmd = MAP_DOM_MEM;
-    dop.u.dommem.start_pfn = pfn;
-    dop.u.dommem.tot_pages = pages;
-    dop.u.dommem.domain = dom;
-
-    /* open the /proc command interface */
-    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
-    cmd_fd = open(cmd_path, O_WRONLY);
-    if ( cmd_fd < 0 )
-    {
-        perror(PERR_STRING);
-        return -1;
-    }
-
-    write(cmd_fd, &dop, sizeof(dom0_op_t));
-    close(cmd_fd);
-
-    return 0;
-}
-      
-/* request the actual mapping from dom0 */
-static unsigned long get_vaddr(unsigned int dom)
-{
-    char mem_path[MAX_PATH];
-    unsigned long addr;
-    int mem_fd;
-
-    /* open the domain's /proc mem interface */
-    sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/", 
-            PROC_DOM_PREFIX, dom, "/", PROC_DOM_MEM);
-
-    mem_fd = open(mem_path, O_RDONLY);
-    if(mem_fd < 0){
-        perror(PERR_STRING);
-        return 0;
-    }
-
-    /* get virtual address of mapped region */
-    read(mem_fd, &addr, sizeof(addr));
-       
-    close(mem_fd);
-
-    return addr;
-}
-
 static int map_dom_mem(unsigned long pfn, int pages, int dom, 
                        dom_mem_t * dom_mem)
 {
-  struct dom0_mapdommem_args argbuf;
-  int fd;
+    struct dom0_mapdommem_args argbuf;
+    int fd;
 
-  argbuf.domain = dom;
-  argbuf.start_pfn = pfn;
-  argbuf.tot_pages = pages;
+    argbuf.domain = dom;
+    argbuf.start_pfn = pfn;
+    argbuf.tot_pages = pages;
   
-  fd = open("/proc/xeno/dom0_cmd", O_RDWR);
-  if (fd < 0) {
-    perror("openning /proc/xeno/dom0_cmd");
-    return -1;
-  }
+    fd = open("/proc/xeno/dom0_cmd", O_RDWR);
+    if (fd < 0) {
+        perror("openning /proc/xeno/dom0_cmd");
+        return -1;
+    }
   
-  dom_mem->domain = dom;
-  dom_mem->start_pfn = pfn;
-  dom_mem->tot_pages = pages;
-  dom_mem->vaddr = ioctl(fd, IOCTL_DOM0_MAPDOMMEM, &argbuf);
-
-  if (dom_mem->vaddr == -1) {
-    perror("mapping domain memory");
-    return -1;
-  }
+    dom_mem->domain = dom;
+    dom_mem->start_pfn = pfn;
+    dom_mem->tot_pages = pages;
+    dom_mem->vaddr = ioctl(fd, IOCTL_DOM0_MAPDOMMEM, &argbuf);
+    
+    if (dom_mem->vaddr == -1) {
+        perror("mapping domain memory");
+       return -1;
+    }
 
-  return 0;
+    return 0;
 }
 
 /* open kernel image and do some sanity checks */
@@ -215,14 +161,13 @@ static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd,
     dom_meminfo_t *meminfo;
     unsigned long *page_array;
     page_update_request_t *pgt_updates;
-    dom_mem_t mem_map;
     dom_meminfo_t *ret = NULL;
     int alloc_index, num_pt_pages;
     unsigned long l2tab;
     unsigned long l1tab = 0;
     unsigned long num_pgt_updates = 0;
     unsigned long count, pt_start;
-    dom0_op_t pgupdate_req;
+    struct dom0_dopgupdates_args pgupdate_req;
     char cmd_path[MAX_PATH];
     int cmd_fd;
 
@@ -324,10 +269,9 @@ static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd,
      */
     sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
     if ( (cmd_fd = open(cmd_path, O_WRONLY)) < 0 ) goto out;
-    pgupdate_req.cmd = DO_PGUPDATES;
-    pgupdate_req.u.pgupdate.pgt_update_arr  = (unsigned long)dom_mem->vaddr;
-    pgupdate_req.u.pgupdate.num_pgt_updates = num_pgt_updates;
-    write(cmd_fd, &pgupdate_req, sizeof(dom0_op_t));
+    pgupdate_req.pgt_update_arr  = (unsigned long)dom_mem->vaddr;
+    pgupdate_req.num_pgt_updates = num_pgt_updates;
+    if (ioctl(cmd_fd, IOCTL_DOM0_DOPGUPDATES, &pgupdate_req) < 0) goto out;
     close(cmd_fd);
 
     /* Load the guest OS image. */
@@ -435,11 +379,9 @@ int main(int argc, char **argv)
 {
 
     dom_mem_t dom_os_image;
-    dom_mem_t dom_pgt; 
     dom_meminfo_t * meminfo;
     size_t ksize;
     unsigned long load_addr;
-    char status[1024];
     int kernel_fd, initrd_fd = 0;
     int count;
     int cmd_len;
@@ -450,8 +392,6 @@ int main(int argc, char **argv)
     int pg_head;
     int tot_pages;
 
-    unsigned long addr;
-
     /**** this argument parsing code is really _gross_. rewrite me! ****/
 
     if(argc < 4) {
index 6286f11b98949d086e313dd6bad565d5cc17816b..b6df8bee46aae32f65723cb53f75789005ccb642 100644 (file)
@@ -118,25 +118,32 @@ typedef struct dom0_op_st
 #define IOCTL_DOM0_CREATEDOMAIN _IOC(_IOC_READ, 'x', 0, sizeof(struct dom0_createdomain_args))
 #define IOCTL_DOM0_MAPDOMMEM _IOC(_IOC_READ, 'x', 1, sizeof(struct dom0_mapdommem_args))
 #define IOCTL_DOM0_UNMAPDOMMEM _IOC(_IOC_READ, 'x', 2, sizeof(struct dom0_unmapdommem_args))
+#define IOCTL_DOM0_DOPGUPDATES _IOC(_IOC_READ, 'x', 3, sizeof(struct dom0_dopgupdates_args))
 
 struct dom0_createdomain_args
 {
-  unsigned int kb_mem;
-  const char *name;
+    unsigned int kb_mem;
+    const char *name;
 };
 
 struct dom0_mapdommem_args
 {
-  unsigned int domain;
-  unsigned start_pfn;
-  unsigned tot_pages;  
+    unsigned int domain;
+    unsigned start_pfn;
+    unsigned tot_pages;  
 };
 
 struct dom0_unmapdommem_args
 {
-  unsigned long vaddr;
-  unsigned long start_pfn;
-  unsigned long tot_pages;
+    unsigned long vaddr;
+    unsigned long start_pfn;
+    unsigned long tot_pages;
+};
+
+struct dom0_dopgupdates_args
+{
+    unsigned long pgt_update_arr;
+    unsigned long num_pgt_updates;
 };
 
 #endif
index 496a8ce2793c7b59cc912eb8a16108abf84bf6b5..7570982feeed600c264502fd03d5c417f8e9fff8 100644 (file)
@@ -162,8 +162,8 @@ static int dom0_cmd_write(struct file *file, const char *buffer, size_t size,
     }
     else if ( op.cmd == DO_PGUPDATES )
     {
-        ret = HYPERVISOR_pt_update((void *)op.u.pgupdate.pgt_update_arr,
-                                   op.u.pgupdate.num_pgt_updates);
+        /* Now an ioctl. */
+        ret = -EOPNOTSUPP;
     }
     else if (op.cmd == DOM0_CREATEDOMAIN)
     {
@@ -274,6 +274,8 @@ static struct file_operations proc_xeno_domains_operations = {
     release:        seq_release,
 };
 
+/* END OF /proc/xeno/domains */
+
 static int handle_dom0_cmd_createdomain(unsigned long data)
 {
   struct dom0_createdomain_args argbuf;
@@ -344,6 +346,18 @@ static int handle_dom0_cmd_unmapdommem(unsigned long data)
                      argbuf.tot_pages << PAGE_SHIFT);
 }
 
+static int handle_dom0_cmd_dopgupdates(unsigned long data)
+{
+  struct dom0_dopgupdates_args argbuf;
+
+  if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
+    return -EFAULT;
+
+  /* argbuf.pgt_update_arr had better be direct mapped... */
+  return HYPERVISOR_pt_update(argbuf.pgt_update_arr,
+                             argbuf.num_pgt_updates);
+}
+
 static int dom0_cmd_ioctl(struct inode *inode, struct file *file,
                          unsigned int cmd, unsigned long data)
 {
@@ -355,6 +369,8 @@ static int dom0_cmd_ioctl(struct inode *inode, struct file *file,
     return handle_dom0_cmd_mapdommem(data);
   case IOCTL_DOM0_UNMAPDOMMEM:
     return handle_dom0_cmd_unmapdommem(data);
+  case IOCTL_DOM0_DOPGUPDATES:
+    return handle_dom0_cmd_dopgupdates(data);
   default:
     printk("Unknown dom0_cmd ioctl!\n");
     return -EINVAL;
index 3e3ff19fca263eb14a5ade8b88cc6495c95efcb9..e2f14db03f078905812240f9a357398cbf1ad3df 100644 (file)
@@ -32,90 +32,45 @@ extern struct list_head * find_direct(struct list_head *, unsigned long);
 #define __direct_mk_pte(page_nr,pgprot) __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
 #define direct_mk_pte_phys(physpage, pgprot)   __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
 
-static inline void forget_pte(pte_t page)
-{
-    if (!pte_none(page)) {
-        printk("forget_pte: old mapping existed!\n");
-        BUG();
-    }
-}
+/*  Note: this is only safe if the mm semaphore is held when called. */
 
-static inline void direct_remappte_range(pte_t * pte, unsigned long address, unsigned long size,
-                                         unsigned long phys_addr, pgprot_t prot)
+static int direct_remap_page(unsigned long from, unsigned long phys_addr, pgprot_t prot)
 {
-    unsigned long end;
+    struct mm_struct *mm = current->mm;
+    pgd_t * dir;
+    pmd_t *pmd;
+    pte_t *pte;
 
-    address &= ~PMD_MASK;
-    end = address + size;
-    if (end > PMD_SIZE)
-        end = PMD_SIZE;
-    do {
-        pte_t oldpage;
-        oldpage = ptep_get_and_clear(pte);
+    pte_t oldpage;
 
-        direct_set_pte(pte, direct_mk_pte_phys(phys_addr, prot));
+    dir = pgd_offset(mm, from);
+    flush_cache_range(mm, from, from + PAGE_SIZE);
+    
+    spin_lock(&mm->page_table_lock);
+    pmd = pmd_alloc(mm, dir, from);
+    if (!pmd)
+       return -ENOMEM;
+    pte = pte_alloc(mm, pmd, address);
+    if (!pte) {
+       /* XXX free pmd? */
+       return -ENOMEM;
+    }
 
-        forget_pte(oldpage);
-        address += PAGE_SIZE;
-        phys_addr += PAGE_SIZE;
-        pte++;
-    } while (address && (address < end));
+    /* Sanity check */
+    oldpage = ptep_get_and_clear(pte);
+    if (!pte_none(oldpage)) {
+        printk("Page already in use!\n");
+        BUG();
+    }
+    direct_set_pte(pte, direct_mk_pte_phys(phys_addr, prot));
 
-}
+    spin_unlock(&mm->page_table_lock);
 
-static inline int direct_remappmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-                                        unsigned long phys_addr, pgprot_t prot)
-{
-    unsigned long end;
+    flush_tlb_range(mm, from, from + PAGE_SIZE);
 
-    address &= ~PGDIR_MASK;
-    end = address + size;
-    if (end > PGDIR_SIZE)
-        end = PGDIR_SIZE;
-    phys_addr -= address;
-    do {
-        pte_t * pte = pte_alloc(mm, pmd, address);
-        if (!pte)
-            return -ENOMEM;
-        direct_remappte_range(pte, address, end - address, address + phys_addr, prot);
-        address = (address + PMD_SIZE) & PMD_MASK;
-        pmd++;
-    } while (address && (address < end));
     return 0;
 }
 
-/*  Note: this is only safe if the mm semaphore is held when called. */
-static int direct_remap_page_range(unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot)
-{
-    int error = 0;
-    pgd_t * dir;
-    unsigned long beg = from;
-    unsigned long end = from + size;
-    struct mm_struct *mm = current->mm;
-
-    phys_addr -= from;
-    dir = pgd_offset(mm, from);
-    flush_cache_range(mm, beg, end);
-    if (from >= end)
-        BUG();
-
-    spin_lock(&mm->page_table_lock);
-    do {
-        pmd_t *pmd = pmd_alloc(mm, dir, from);
-        error = -ENOMEM;
-        if (!pmd)
-            break;
-        error = direct_remappmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
-        if (error)
-            break;
-        from = (from + PGDIR_SIZE) & PGDIR_MASK;
-        dir++;
-    } while (from && (from < end));
-    spin_unlock(&mm->page_table_lock);
-    flush_tlb_range(mm, beg, end);
-    return error;
-}
-
 /* 
  * used for remapping discontiguous bits of domain's memory, pages to map are
  * found from frame table beginning at the given first_pg index
@@ -142,8 +97,8 @@ static int direct_remap_disc_page_range(unsigned long from,
 
         for ( i = 0; i < pages; i++ )
         {
-            if(direct_remap_page_range(start, pfns[i] << PAGE_SHIFT, 
-                                       PAGE_SIZE, prot))
+            if(direct_remap_page(start, pfns[i] << PAGE_SHIFT, 
+                                prot))
                 goto out;
             start += PAGE_SIZE;
             tot_pages--;
@@ -155,10 +110,10 @@ static int direct_remap_disc_page_range(unsigned long from,
     return tot_pages;
 } 
            
-/* below functions replace standard sys_mmap and sys_munmap which are absolutely useless
- * for direct memory mapping. direct_zap* functions are minor ammendments to the 
- * original versions in mm/memory.c. the changes are to enable unmapping of real physical
- * addresses.
+/* below functions replace standard sys_mmap and sys_munmap which are
+ * absolutely useless for direct memory mapping. direct_zap* functions
+ * are minor ammendments to the original versions in mm/memory.c. the
+ * changes are to enable unmapping of real physical addresses.
  */
 
 unsigned long direct_mmap(unsigned long phys_addr, unsigned long size, 
@@ -169,6 +124,9 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
     unsigned long addr;
     int ret = 0;
     
+    if(!(size & ~PAGE_MASK))
+       return -EINVAL;
+
     if(!capable(CAP_SYS_ADMIN))
         return -EPERM;
 
@@ -185,16 +143,16 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
     dmmap->vm_end = addr + size;
     entry = find_direct(&current->mm->context.direct_list, addr);
     if(entry != &current->mm->context.direct_list){
-      list_add_tail(&dmmap->list, entry);
+       list_add_tail(&dmmap->list, entry);
     } else {
-      list_add_tail(&dmmap->list, &current->mm->context.direct_list);
+       list_add_tail(&dmmap->list, &current->mm->context.direct_list);
     }
 
-    /* XXX kfree(dmmap)? */
-
+    /* Acquire mm sem? */
     /* and perform the mapping */
     ret = direct_remap_disc_page_range(addr, phys_addr >> PAGE_SHIFT, 
                                       tot_pages, prot);
+    /* Drop mm sem? */
 
     if(ret == 0)
         return addr;
@@ -202,75 +160,19 @@ unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
         return ret;
 }
 
-/* most of the checks, refcnt updates, cache stuff have been thrown out as they are not
- * needed
- */
-static inline int direct_zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, 
-                                       unsigned long size)
-{
-    unsigned long offset;
-    pte_t * ptep;
-    int freed = 0;
-
-    if (pmd_none(*pmd))
-        return 0;
-    if (pmd_bad(*pmd)) {
-        pmd_ERROR(*pmd);
-        pmd_clear(pmd);
-        return 0;
-    }
-    ptep = pte_offset(pmd, address);
-    offset = address & ~PMD_MASK;
-    if (offset + size > PMD_SIZE)
-        size = PMD_SIZE - offset;
-    size &= PAGE_MASK;
-    for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) {
-        pte_t pte = *ptep;
-        if (pte_none(pte))
-            continue;
-        freed ++;
-        direct_pte_clear(ptep);
-    }
-
-    return freed;
-}
-
-static inline int direct_zap_pmd_range(mmu_gather_t *tlb, pgd_t * dir, 
-                                       unsigned long address, unsigned long size)
-{
-    pmd_t * pmd;
-    unsigned long end;
-    int freed;
-
-    if (pgd_none(*dir))
-        return 0;
-    if (pgd_bad(*dir)) {
-        pgd_ERROR(*dir);
-        pgd_clear(dir);
-        return 0;
-    }
-    pmd = pmd_offset(dir, address);
-    end = address + size;
-    if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
-        end = ((address + PGDIR_SIZE) & PGDIR_MASK);
-    freed = 0;
-    do {
-        freed += direct_zap_pte_range(tlb, pmd, address, end - address);
-        address = (address + PMD_SIZE) & PMD_MASK; 
-        pmd++;
-    } while (address < end);
-    return freed;
-}
-
 /*
- * remove user pages in a given range.
+ * remove a user page
+ *
+ * There used to be a function here which could remove a whole range
+ * of pages, but it was only ever called with that range equal to a
+ * single page, so I simplified it a bit -- sos22.
  */
-static void direct_zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
+static void direct_zap_page(struct mm_struct *mm, unsigned long address)
 {
     mmu_gather_t *tlb;
     pgd_t * dir;
-    unsigned long start = address, end = address + size;
-    int freed = 0;
+    pmd_t * pmd;
+    pte_t * pte;
 
     dir = pgd_offset(mm, address);
 
@@ -281,20 +183,14 @@ static void direct_zap_page_range(struct mm_struct *mm, unsigned long address, u
      * even if kswapd happened to be looking at this
      * process we _want_ it to get stuck.
      */
-    if (address >= end)
-        BUG();
     spin_lock(&mm->page_table_lock);
-    flush_cache_range(mm, address, end);
+    flush_cache_range(mm, address, address + PAGE_SIZE);
+    
     tlb = tlb_gather_mmu(mm);
-
-    do {
-        freed += direct_zap_pmd_range(tlb, dir, address, end - address);
-        address = (address + PGDIR_SIZE) & PGDIR_MASK;
-        dir++;
-    } while (address && (address < end));
-
-    /* this will flush any remaining tlb entries */
-    tlb_finish_mmu(tlb, start, end);
+    pmd = pmd_offset(dir, address);
+    pte = pte_offset(pmd, address);
+    direct_pte_clear(pte);
+    tlb_finish_mmu(tlb, address, address + PAGE_SIZE);
 
     /* decrementing rss removed */
     spin_unlock(&mm->page_table_lock);
@@ -303,16 +199,16 @@ static void direct_zap_page_range(struct mm_struct *mm, unsigned long address, u
 
 int direct_unmap(struct mm_struct *mm, unsigned long addr, unsigned long size)
 {
-    int count = 0, tot_pages = (size+PAGE_SIZE-1) >> PAGE_SHIFT;
     direct_mmap_node_t * node;
     struct list_head * curr;
     struct list_head * direct_list = &mm->context.direct_list;    
+    unsigned long end;
 
     curr = direct_list->next;
     while ( curr != direct_list )
     {
         node = list_entry(curr, direct_mmap_node_t, list);
-        if ( node->vm_start == addr )
+        if ( node->vm_start == addr && node->vm_end == addr + size)
             break;
         curr = curr->next;
     }
@@ -323,11 +219,17 @@ int direct_unmap(struct mm_struct *mm, unsigned long addr, unsigned long size)
     list_del(&node->list);
     kfree(node);
 
-    while ( count < tot_pages )
+    if (size & ~PAGE_MASK) {
+       printk("Managed to map something which isn\'t a multiple of a page size...\n");
+       BUG();
+       return -EINVAL;
+    }
+
+    end = addr + size;
+    while ( addr < end )
     {
-        direct_zap_page_range(mm, addr, PAGE_SIZE);
+        direct_zap_page(mm, addr);
         addr += PAGE_SIZE;
-        count++;
     }
 
     return 0;